/*
 * Scene.cc
 *
 *  Created on: Jan 9, 2013
 *      Author: Zermingore
 */

#include "Scene.hh"
#include "globals/engines.h"
#include "core/GraphicEngine.hh"
#include "tools/Vector.hh"
#include "tools/Matrix.hh"
#include "graphics/Light.hh"
#include "graphics/Mesh.hh"
#include "media/Shader.hh"
#include "core/Context.hh"
#include "graphics/DirectionalLight.hh"


#ifdef DEBUG
    GraphicEngine g_graphicEngine (30.0f, 4.0f/3.0f, 1.0f, 100.0f);
#else
    GraphicEngine g_graphicEngine (30.0f, 1.6f, 1.0f, 100.0f); // ask sys 4 ratio
#endif


Scene::Scene() :
    _worldLocation (0),
    _vbo (0),
    _ibo (0)
{
    // should ask 4 ratio in options or ask system
    #ifdef DEBUG
        _ratio = 4.0f / 3.0f;
    #else
        _ratio = 16.0f / 9.0f;
    #endif

    //_graphicEngine = new GraphicEngine(30.0f, 1.3333f, 1.0f, 100.0f);

    _t = new Texture(GL_TEXTURE_2D, "resources/textures/test.png");
    _t->Load();
}

Scene::~Scene()
{
    // Cleaning buffers
    // glDeleteBuffers(1, &vertexbuffer);

    //glDeleteProgram(programID);

    // glDeleteVertexArrays(1, &VertexArrayID);

    // free all 3D models
}


void Scene::fillVertexBuffer()
{
    Vector Vertices[4];

    Vertices[0] = Vector(-1.0f, -1.0f, 0.5773f);
    Vertices[1] = Vector(0.0f, -1.0f, -1.15475);
    Vertices[2] = Vector(1.0f, -1.0f, 0.5773f);
    Vertices[3] = Vector(0.0f, 1.0f, 0.0f);

    glGenBuffers(1, &_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}


void Scene::createIndices()
{
    unsigned int Indices[] = {0, 3, 1,
                              1, 3, 2,
                              2, 3, 0,
                              0, 2, 1};

    glGenBuffers(1, &_ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
}


void Scene::renderScene()
{
    glClear(GL_COLOR_BUFFER_BIT);

    #ifdef DEBUG
        // makes the background more visible
        glClearColor(255, 0, 255, 255);
    #endif

    Matrix model(true); // loading identity

    //model.rotate(scale, Vector(0,1,0));
    //model.scale(Vector(1, scale, 1));
    //model.translate(Vector(0, 0, -scale));

    g_graphicEngine.setModel(model);
    g_graphicEngine.updatePerspective();

    glUniformMatrix4fv(_worldLocation, 1, GL_TRUE, g_graphicEngine.getMVP().getValues());
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vector), 0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vector), (const GLvoid*)12);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);

    _t->Bind(GL_TEXTURE0);
    glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);

    glDisableVertexAttribArray(0);
}

void Scene::init()
{
    Matrix cameraPosition(true); // true: loading identity

    cameraPosition[0][3] = 0;
    cameraPosition[1][3] = 0;
    cameraPosition[2][3] = 8;

    g_graphicEngine.setCamera(cameraPosition);
    g_graphicEngine.updatePerspective();

    fillVertexBuffer();
    createIndices();

    // Shaders
    // TODO move in a Shader Manager
    Shader* shader = new Shader("texture");
    shader->init();
    GLuint programID = shader->getProgramId();
    glUseProgram(programID);

    _worldLocation = glGetUniformLocation(programID, "MVP");
    if ((unsigned int) _worldLocation == 0xFFFFFFFF)
        std::cerr << "Wrong Uniform Location" << _worldLocation << std::endl;

    DirectionalLight* light;
    light = new DirectionalLight(Vector (1, 1, 1), 0.3, programID);
    light->on();
}


void Scene::draw()
{
    renderScene();
}

void Scene::addMesh(std::string name, Vector position)
{

}


//void Scene::addmesh(Mesh mesh);

void Scene::addLight(std::string name, Vector position)
{

}


void Scene::addLight(e_light light)
{

}
